/**
 * PassivePSSThread.java
 * ************************** 
 * @date Mar 21, 2011
 * @author Michele Tamburini
 * 
 * **************************
 */
package gossipServices.pss;

import gossipServices.basic.nodeDescriptors.ConcreteNodeDescriptor;
import gossipServices.basic.nodeDescriptors.NodeDescriptor;
import gossipServices.basic.view.ConcretePartialView;
import gossipServices.basic.view.PartialView;
import gossipServices.gossipMessages.PssMessage;
import gossipServices.gossipThread.PassiveGossipThread;
import gossipServices.network.NetworkServicesAPI;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;

import messages.Message;

/**
 * 
 * Description: 
 * It extends the PassiveGossipThread and contains all actions performed
 * by the passive thread of the Peer Sampling Service.
 *
 */
public class PassivePSSThread extends PassiveGossipThread {

	protected NetworkServicesAPI nia;
	protected boolean push = true, pull;
	protected int H, S;
	
	private boolean SHOW_VIEW = false;
	
	private Logger log = Logger.getLogger("PassivePSS_log");
	
	/**
	 * @param name
	 * @param cycleLenghtMsec
	 * @param view
	 * @param pull2 
	 * @param push2 
	 * @param s 
	 * @param h 
	 * @param serviceLevel 
	 * @param gossipProtocol
	 */
	public PassivePSSThread(String name, long cycleLenghtMsec, PartialView view, 
			NetworkServicesAPI net, int h, int s, boolean push2, boolean pull2) {
		super(name, cycleLenghtMsec, view);
		nia = net;
		H = h;
		S = s;
		push = push2;
		pull = pull2;
		log.setLevel(Level.OFF);
	}

	@Override
	public void passiveThreadInstructions() throws InterruptedException {
		PartialView bufferp;
		PartialView buffer = new ConcretePartialView(0);
		log.info("starting passive thread\n waiting for incoming messages");
		Message m = nia.receive();
		log.info("PASSIVE THREAD: received message "+m);
		NodeDescriptor p = m.getSender();
		
		log.info("creating bufferp");
		bufferp = (PartialView) m.getBody();
		
		NodeDescriptor myDescriptor = null;
		try {
			myDescriptor = new ConcreteNodeDescriptor(nia.getNodeName(),
					InetAddress.getLocalHost(),new Integer(0));
			buffer.insertNodeDescriptor(myDescriptor);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}

		if(pull){
			//0 is the initial age
			//access to the view 
			synchronized (view) {
				view.permute(H);
				buffer.append(view.head(view.size()/2-1));
				view.notify();
			}
			Message msg = new PssMessage(buffer, myDescriptor, p, this.getClass());
			log.info(Thread.currentThread().getName()+"sending message "+ m +" to p: "+p);
			nia.send(msg, p);					
		}
		synchronized (view) {
			view.select(view.size(), H, S, bufferp, myDescriptor);
			view.increaseAge();			
			log.info("selection and view increment");
			view.notify();
			if(SHOW_VIEW)
				System.out.print(nia.getNodeName()+" view:\n"+view+"\n");
		}
	}
	
	public boolean enableShowView(){
		SHOW_VIEW = true;
		return SHOW_VIEW;
	}
	
	public boolean disableShowView(){
		SHOW_VIEW = false;
		return SHOW_VIEW;
	}

}
